/*
 * 版权所有 (C) 2015 知启蒙(ZHIQIM) 保留所有权利。[遇见知启蒙，邂逅框架梦]
 * 
 * https://zhiqim.org/project/zhiqim_framework/zhiqim_kernel.htm
 *
 * Zhiqim Kernel is licensed under Mulan PSL v2.
 * You can use this software according to the terms and conditions of the Mulan PSL v2.
 * You may obtain a copy of Mulan PSL v2 at:
 *          http://license.coscl.org.cn/MulanPSL2
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 * See the Mulan PSL v2 for more details.
 */
package org.zhiqim.kernel.json;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.sql.Time;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;

import org.zhiqim.kernel.json.parser.ArrayParser;
import org.zhiqim.kernel.json.parser.BaseParser;
import org.zhiqim.kernel.json.parser.DateParser;
import org.zhiqim.kernel.json.parser.JsonStringParser;
import org.zhiqim.kernel.json.parser.ListParser;
import org.zhiqim.kernel.json.parser.MapParser;
import org.zhiqim.kernel.json.parser.MapSOParser;
import org.zhiqim.kernel.json.parser.MapSSParser;
import org.zhiqim.kernel.json.parser.MapSVParser;
import org.zhiqim.kernel.json.parser.ObjectParser;
import org.zhiqim.kernel.model.lists.ConcurrentSet;
import org.zhiqim.kernel.model.maps.HashMapCV;
import org.zhiqim.kernel.model.maps.HashMapSO;
import org.zhiqim.kernel.model.maps.HashMapSS;
import org.zhiqim.kernel.model.maps.HashMapSV;
import org.zhiqim.kernel.model.maps.LinkedMapSO;
import org.zhiqim.kernel.model.maps.LinkedMapSS;
import org.zhiqim.kernel.model.maps.LinkedMapSV;
import org.zhiqim.kernel.model.maps.MapSO;
import org.zhiqim.kernel.model.maps.MapSS;
import org.zhiqim.kernel.model.maps.MapSV;
import org.zhiqim.kernel.model.maps.TreeMapSO;
import org.zhiqim.kernel.model.maps.TreeMapSS;
import org.zhiqim.kernel.model.maps.TreeMapSV;
import org.zhiqim.kernel.util.Classes;

/**
 * JSON 主程序，对象转换成JSON和JSON转换成对象
 *
 * @version v1.0.0 @author zouzhigang 2014-3-21 新建与整理
 */
public class Json
{
    //定义一个通用Json实例
    public static final Json json = new Json();
    
    //Json解析器哈希表
    private final HashMapCV<JsonParser> parserMap;
    
    public Json()
    {
        this.parserMap = new HashMapCV<JsonParser>();
        this.initParser();
    }

    /*****************************************************************************************/
    //初始化解析器
    /*****************************************************************************************/
    
    private void initParser()
    {
        //8种基本类型、 字符串和特殊字数字型
        JsonParser parser = new BaseParser();
        putParsers(parser, boolean.class, byte.class, char.class, short.class, int.class, long.class, float.class, double.class);
        putParsers(parser, Boolean.class, Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class);
        putParsers(parser, String.class, BigInteger.class, BigDecimal.class, AtomicInteger.class, AtomicLong.class);
        
        //数组类型，8种基本类型数组、字符串数组、特殊字数字数组和通用的Object[]
        parser = new ArrayParser(this);
        putParsers(parser, boolean[].class, byte[].class, char[].class, short[].class, int[].class, long[].class, float[].class, double[].class);
        putParsers(parser, Boolean[].class, Byte[].class, Character[].class, Short[].class, Integer[].class, Long[].class, Float[].class, Double[].class);
        putParsers(parser, String[].class, BigInteger[].class, BigDecimal[].class, AtomicInteger[].class, AtomicLong[].class);
        putParsers(parser, Object[].class);
        
        //特殊字符串&通用对象
        putParser(JsonString.class, new JsonStringParser());
        putParser(Object.class, new ObjectParser(this));
        
        //链表
        parser = new ListParser(this);
        putParsers(parser, Collection.class, List.class, ArrayList.class, LinkedList.class);
        putParsers(parser, Set.class, HashSet.class, ConcurrentSet.class);
        
        //哈希表
        parser = new MapParser(this);
        putParsers(parser, Map.class, HashMap.class, LinkedHashMap.class, TreeMap.class);
        putParsers(parser, Hashtable.class, ConcurrentMap.class, ConcurrentHashMap.class);
        
        //知启蒙哈希表
        putParsers(new MapSOParser(this), MapSO.class, HashMapSO.class, LinkedMapSO.class, TreeMapSO.class);
        putParsers(new MapSSParser(this), MapSS.class, HashMapSS.class, LinkedMapSS.class, TreeMapSS.class);
        putParsers(new MapSVParser(this), MapSV.class, HashMapSV.class, LinkedMapSV.class, TreeMapSV.class);
        
        //日期对象
        putParsers(new DateParser(), java.util.Date.class, java.sql.Date.class, Time.class, Timestamp.class, Calendar.class);
    }
    
    /** 设置解析器 */
    private Json putParsers(JsonParser parser, Class<?>... clss)
    {
        for (Class<?> cls : clss)
            parserMap.put(cls, parser);
        return this;
    }
    
    /** 设置解析器 */
    public Json putParser(Class<?> cls, JsonParser parser)
    {
        parserMap.put(cls, parser);
        return this;
    }
    
    /** 获取解析器 */
    public JsonParser getParser(Class<?> cls)
    {
        JsonParser parser = parserMap.get(cls);
        if (parser != null)
            return parser;
        
        //列表/哈希表/数组，其他的认为是对象
        if (Classes.isCollection(cls))
            return parserMap.get(List.class);
        else if (Classes.isMap(cls))
            return parserMap.get(Map.class);
        else if (cls.isArray())
            return parserMap.get(Object[].class);
        else
            return parserMap.get(Object.class);
    }
    
    /*****************************************************************************************/
    //toString&toObject
    /*****************************************************************************************/
    
    /**
     * 对象转换成JSON字符串
     * 
     * @param obj   对象
     * @return      JSON字符串
     */
    public String toString(Object obj)
    {
        if (obj == null)
            return "null";
        
        return getParser(obj.getClass()).toString(obj);
    }
    
    /**
     * JSON字符串转换成对象
     * 
     * @param json      JSON字符串
     * @param cls       转换成对象的类
     * @return          obj对象
     */
    public <T> T toObject(String json, Class<T> cls)
    {
        return toObject(json, cls, true);
    }
    
    /**
     * JSON字符串转换成对象
     * 
     * @param json      JSON字符串
     * @param cls     转换成对象的类
     * @param chkSpace  是否检查空格
     * @return          obj对象
     */
    @SuppressWarnings("unchecked")
    public <T> T toObject(String json, Class<T> cls, boolean chkSpace)
    {
        if (json == null || cls == null)
            return null;
        
        if (chkSpace)
            json = Jsons.removeBlankSpace(json);
        
        if ("null".equals(json))
            return null;
        
        return (T)getParser(cls).toObject(json, cls);
    }
}
